package com.test;

import com.sc.apiConstant.AlgIdConstants;
import com.sc.hsm.HsmCSPApi;
import com.sc.hsm.HsmCSPApiImpl;
import com.sc.hsm.response.domain.Digest;
import com.sc.hsm.response.domain.ExportPublicKey;
import com.sc.hsm.response.domain.GenerateRandom;
import com.sc.hsm.response.domain.HMAC;
import com.sc.hsm.response.domain.SymmetricDecrypt;
import com.sc.hsm.response.domain.SymmetricEncrypt;
import com.sc.hsm.utils.PaddUtils;
import com.sc.utils.ResultObject;
import com.sc.utils.bc.util.encoders.Hex;

/**
 * @Description 教育局加密机服务工具类
 *
 * @author liuqinghua
 * @date 2025-1-9
 */
public class PwServerUtils {

    public static HsmCSPApi cspApi = new HsmCSPApiImpl();

    public static byte[] publicKey = null;

    private final static String SECRET_KEY = "jsps@jsps@123456";

    public static String encryptBySMS4_ECB(String str) {
        byte[] pad = PaddUtils.pad(str.getBytes(), 16);
        ResultObject<SymmetricEncrypt> symmetricEncryptResultObject = cspApi.symmetricEncrypt(1,
                AlgIdConstants.SGD_SMS4_ECB, (byte[]) null, (byte[]) null, pad);
        if (symmetricEncryptResultObject != null && symmetricEncryptResultObject.getCode() == 0) {
            return ((SymmetricEncrypt) symmetricEncryptResultObject.getData()).getOutData();
        } else {
            throw new RuntimeException("调用加密机加密异常");
        }
    }

    public static String decryptBySMS4_ECB(String str) {
        ResultObject<SymmetricDecrypt> symmetricDecryptResultObject = cspApi.symmetricDecrypt(1,
                AlgIdConstants.SGD_SMS4_ECB, (byte[]) null, (byte[]) null, Hex.decode(str));
        if (symmetricDecryptResultObject != null && symmetricDecryptResultObject.getCode() == 0) {
            byte[] unpad = PaddUtils
                    .unpad(((SymmetricDecrypt) symmetricDecryptResultObject.getData()).getOutDataBytes(), 16);
            return new String(unpad);
        } else {
            throw new RuntimeException("调用加密机解密异常");
        }
    }

    private static byte[] getPublicKey() {
        if (publicKey == null) {
            synchronized (PwServerUtils.class) {
                ResultObject<ExportPublicKey> exportPublicKeyResultObject = cspApi.exportPublicKey(0, 1);
                if (exportPublicKeyResultObject != null && exportPublicKeyResultObject.getCode() == 0) {
                    return ((ExportPublicKey) exportPublicKeyResultObject.getData()).getPublicKeyBytes();
                } else {
                    throw new RuntimeException("调用密码机初始化公钥异常异常");
                }
            }
        } else {
            return publicKey;
        }
    }

    /**
     * 杂凑
     * 
     * @param str
     * @return
     */
    public static String digest(String str) {
        ResultObject<Digest> digest = cspApi.digest(getPublicKey(), SECRET_KEY.getBytes(), str.getBytes());
        if (digest != null && digest.getCode() == 0) {
            return (((Digest) digest.getData()).getHashData());
        } else {
            throw new RuntimeException("调用密码机杂凑常异常");
        }
    }

    /**
     * HMAC
     * 
     * @param str
     * @return
     */
    public static String hmac(String str) {
        ResultObject<HMAC> hmac = cspApi.hmac(1, (byte[]) null, AlgIdConstants.SGD_SM3, str.getBytes());
        if (hmac != null && hmac.getCode() == 0) {
            return ((HMAC) hmac.getData()).getHmac();
        } else {
            throw new RuntimeException("调用密码机HMAC异常");
        }
    }

    /**
     * 密码加密（先HMAC，再杂凑）
     * 
     * @param md5Pw
     * @return
     */
    public static String encodePw(String md5Pw) {
        return digest(hmac(md5Pw));
    }

    public static String generateRandom(int length) {
        ResultObject<GenerateRandom> generateRandom = cspApi.generateRandom(length);
        if (generateRandom != null && generateRandom.getCode() == 0) {
            return ((GenerateRandom) generateRandom.getData()).getRandom();
        } else {
            System.out.println(generateRandom);
            throw new RuntimeException("调用密码机生产随机码异常");
        }
    }

    public static String encryptBySMS4_CBC(String str, String iv) {
        byte[] pad = PaddUtils.pad(str.getBytes(), 16);
        ResultObject<SymmetricEncrypt> symmetricEncryptResultObject = cspApi.symmetricEncrypt(1,
                AlgIdConstants.SGD_SMS4_CBC, (byte[]) null, iv.getBytes(), pad);
        if (symmetricEncryptResultObject != null && symmetricEncryptResultObject.getCode() == 0) {
            return ((SymmetricEncrypt) symmetricEncryptResultObject.getData()).getOutData();
        } else {
            System.out.println(symmetricEncryptResultObject);
            throw new RuntimeException("调用加密机加密异常");
        }
    }

    public static String decryptBySMS4_CBC(String str, String iv) {
        ResultObject<SymmetricDecrypt> symmetricDecryptResultObject = cspApi.symmetricDecrypt(1,
                AlgIdConstants.SGD_SMS4_CBC, (byte[]) null, iv.getBytes(), Hex.decode(str.getBytes()));
        if (symmetricDecryptResultObject != null && symmetricDecryptResultObject.getCode() == 0) {
            byte[] unpad = PaddUtils
                    .unpad(((SymmetricDecrypt) symmetricDecryptResultObject.getData()).getOutDataBytes(), 16);
            return new String(unpad);
        } else {
            System.out.println(symmetricDecryptResultObject);
            throw new RuntimeException("调用加密机解密异常");
        }
    }
}
